/* 
 * File:   Deck.cpp
 * Author: Pouja
 * 
 * Created on 11 augustus 2012, 14:00
 */

#include "Deck.h"

/**
 * Empty constructor
 */
Deck::Deck() {
    std::cout<<"Deck created"<<std::endl;
}

/**
 * Adds a card to the front of the deck
 * @param c The card to be added
 */
void Deck::addCard(Card* c){
    cards.push_front(c);
}

/**
 * Removes the first occurence a card
 * @param c The card to be removed
 */
void Deck::removeCard(Card* c){
    cards.erase(find(c));
}

void Deck::removeCard(list<Card*>::iterator it){
    cards.erase(it);
}
/**
 * Draws a card and removes it of the deck
 * @return the card on the top of the deck
 */
Card* Deck::drawCard(){
    Card* rCard=*cards.begin();
    removeCard(rCard);
    return rCard;
}

/**
 * Shuffles the deck with the stl shuffle function
 * The runtime is O(n)
 */
void Deck::shuffle(){
    vector<Card*> shuffle(cards.begin(),cards.end());
    std::random_shuffle(shuffle.begin(),shuffle.end());
    cards.assign(shuffle.begin(),shuffle.end());
}

/**
 * Finds a card in the deck
 * @param c The card to be found
 * @return iterator pointing to the card or null if the card wasn't found
 */
list<Card*>::iterator Deck::find(Card* c){
    for(list<Card*>::iterator it=cards.begin();it!=cards.end();it++){
        if((*(*it))==*c){
            return it;
        }
    }
    return NULL;
}

/**
 * 
 * @return the amount of cards in this deck
 */
int Deck::size(){
    return cards.size();
}

/**
 * A help function for stl::equal that states how cards must be compared 
 * @param that Card to be compared
 * @param other Card to be compared
 * @return true if both cards are equal
 */
bool helpCardPred(Card * that, Card * other){
    return ((*that)==(*other));
}

/**
 * Equal methode, two decks are equal if the order and the cards in that order are equal
 * @param other The other deck to be compared to
 * @return true if all the cards are in the same order and are equal
 */
bool Deck::operator ==(const Deck& other){
    if(other.cards.size()==cards.size()){
        return equal(cards.begin(),cards.end(),other.cards.begin(),helpCardPred);
    }
    return false;
}

/**
 * Trys to find a card on the n position
 * @param n the position
 * @return the card on the n position or null if n is bigger than the amount of cards in this deck
 */
Card* Deck::findN(int n){
    assert(n>=0);
    if(n>=cards.size()){
        throw std::out_of_range ("The selected position is out of range!");
    }
    list<Card*>::iterator it=cards.begin();
    for(int i=0;it!=cards.end()&&i<n;it++,i++);
    return (*it);
}

/**
 * Not equal method, reverse of the equal method
 * @param other The other deck to be compared to
 * @return opposite of the equal method
 */
bool Deck::operator !=(const Deck& other){
    return !(*this==other);
}

/**
 * destructor
 */
Deck::~Deck() {
    /* Zie Hand::~Hand voor uitleg waarom dit is weggecommet
    for(list<Card*>::iterator it=cards.begin();it!=cards.end();it++){
        delete *it;
    }*/
    cards.clear();
}
